package org.springblade.modules.door.service.impl;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Date;

import com.alibaba.mqtt.server.ServerProducer;
import com.alibaba.mqtt.server.callback.SendCallback;
import com.aliyun.sdk.service.onsmqtt20200420.models.RegisterDeviceCredentialResponseBody;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.modules.alimqtt.config.AliyunMqttProperties;
import org.springblade.modules.alimqtt.publish.AliMqttUtil;
import org.springblade.modules.alimqtt.service.DeviceCredentialService;
import org.springblade.modules.alimqtt.util.Tool;
import org.springblade.modules.door.dto.DoorDeviceMsgDto;
import org.springblade.modules.door.entity.DoorDevice;
import org.springblade.modules.door.entity.DoorLogFile;
import org.springblade.modules.door.mapper.DoorDeviceMapper;
import org.springblade.modules.door.mapper.DoorLogFileMapper;
import org.springblade.modules.door.service.IDoorDeviceService;
import org.springblade.modules.door.vo.DoorDeviceVo;
import org.springblade.modules.system.entity.Tenant;
import org.springblade.modules.system.mapper.TenantMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;

@Slf4j
@Service
public class IDoorDeviceServiceImpl extends ServiceImpl<DoorDeviceMapper, DoorDevice> implements IDoorDeviceService {
	@Resource
	private DoorDeviceMapper doorDeviceMapper;
	@Resource
	private DeviceCredentialService deviceCredentialService;
	@Resource
	private AliyunMqttProperties aliyunMqttProperties;
	@Resource
	private DoorLogFileMapper doorLogFileMapper;

	@Override
	@Transactional
	public DoorDeviceVo register(String deviceCode, String readerSn) {
		log.info("货物柜设备注册{}",deviceCode+"|"+readerSn);
		LambdaQueryWrapper<DoorDevice> deviceWrapper = Wrappers.lambdaQuery();
		deviceWrapper.eq(DoorDevice::getDeviceCode, deviceCode)
			.last("LIMIT 1");
		DoorDevice doorDevice = doorDeviceMapper.selectOne(deviceWrapper);
		if (Objects.isNull(doorDevice)|| StringUtils.isBlank(doorDevice.getClientId())){
			//没有设备注册配置则需要注册
			RegisterDeviceCredentialResponseBody.DeviceCredential deviceCredential = deviceCredentialService.registerDevice(deviceCode);
			String userName = "Signature|" + aliyunMqttProperties.getAccessKey() + "|" + aliyunMqttProperties.getInstance();
			String password = Tool.macSignature(deviceCredential.getClientId(), aliyunMqttProperties.getSecretKey());
			DoorDevice doorInsert = new DoorDevice();
			doorInsert.setDeviceCode(deviceCode);
			doorInsert.setDeviceKey(deviceCredential.getDeviceAccessKeyId());
			doorInsert.setDeviceSecret(deviceCredential.getDeviceAccessKeySecret());
			doorInsert.setClientId(deviceCredential.getClientId());
			doorInsert.setClientPwd(password);
			doorInsert.setUserName(userName);
			doorInsert.setReaderSn(readerSn);
			doorInsert.setCreateTime(new Date());
			doorInsert.setUpdateTime(new Date());
			doorInsert.setHeartTime(new Date());
			doorDeviceMapper.insert(doorInsert);
			return BeanUtil.copy(doorInsert, DoorDeviceVo.class);

		}
		return BeanUtil.copy(doorDevice, DoorDeviceVo.class);
	}

	@Override
	public boolean sendDoorMsg(DoorDeviceMsgDto doorDeviceMsgDto) {
		AliMqttUtil.sendMsg(doorDeviceMsgDto.getTopic(), doorDeviceMsgDto.getMessage());
		return true;
	}

	@Override
	public void downloadLogUrl(HttpServletRequest request, HttpServletResponse response, String deviceCode, String date) {
		LambdaQueryWrapper<DoorLogFile> logWrapper = Wrappers.lambdaQuery();
		logWrapper.eq(DoorLogFile::getDeviceCode,deviceCode)
			.eq(DoorLogFile::getLogDate,date)
			.orderByDesc(DoorLogFile::getUploadTime)
			.last("LIMIT 1");
		DoorLogFile doorLogFile = doorLogFileMapper.selectOne(logWrapper);
		if (Objects.isNull(doorLogFile)) {
			throw new ServiceException("日志还未上传");
		}
		ServletOutputStream sos = null;
		InputStream inputStream = null;
		try {
			URL url = new URL(doorLogFile.getFullPath());
			URLConnection conn = url.openConnection();
			response.setContentType("text/plain");
			response.setHeader("Content-Disposition", "attachment; filename="
				+ URLEncoder.encode(doorLogFile.getName(), StandardCharsets.UTF_8.name()));
			sos = response.getOutputStream();
			inputStream = conn.getInputStream();
			IOUtils.copy(inputStream, sos);
		} catch (IOException e) {
			throw new RuntimeException(e);
		} finally {
			IOUtils.closeQuietly(sos);
			IOUtils.closeQuietly(inputStream);
		}
	}
}
